package com.though.weixin.utils;

import com.alibaba.fastjson.JSON;
import com.though.utils.encrypt.MD5;
import com.though.utils.tools.DateUtils;
import com.though.weixin.config.PayConfigParams;
import com.though.weixin.params.PayOrderParams;
import com.though.weixin.params.PayRefundParams;
import com.though.weixin.params.SendRedPackParams;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.util.*;

public class PayHelper {

	/**
	 * 签名
	 */
	public static void sign(SortedMap<String, String> params, String key) {
		StringBuffer buffer = new StringBuffer();
		for (Map.Entry<String, String> entry : params.entrySet()) {
			String keys = entry.getKey();
			String value = entry.getValue();
			if (StringUtils.isNotBlank(value) && StringUtils.isNotBlank(keys) && !"sign".equals(keys)) {
				buffer.append(keys + "=" + value + "&");
			}
		}
		buffer.append("key=" + key);
		params.put("sign", MD5.encode(buffer.toString()));
	}

	/**
	 * 创建Map
	 */
	public static SortedMap<String, String> createRequestPayParams(PayOrderParams params, PayConfigParams configParams) {
		SortedMap<String, String> maps = new TreeMap<>();
		maps.put("body", params.getBody());
		maps.put("notify_url", params.getNotify_url());
		maps.put("out_trade_no", params.getOut_trade_no());
		maps.put("spbill_create_ip", params.getSpbill_create_ip());
		maps.put("trade_type", params.getTrade_type());
		maps.put("total_fee", String.valueOf(params.getTotal_fee()));
		maps.put("appid", configParams.getAppid());
		maps.put("mch_id", configParams.getMch_id());
		maps.put("nonce_str", makeUUID());
		if ("JSAPI".equalsIgnoreCase(params.getTrade_type())){//小程序支付
            maps.put("openid",params.getOpenid());
        }

		return maps;
	}

	public static synchronized String makeUUID() {
		StringBuffer s = new StringBuffer(DateFormatUtils.format(new Date(), DateUtils.dateFormat));
		return s.append((new Random().nextInt(900) + 100)).toString();
	}

	public static String mapToXML(SortedMap<String, String> params) {
		StringBuffer buffer = new StringBuffer();
		buffer.append("<xml>");
		for (Map.Entry<String, String> entry : params.entrySet()) {
			buffer.append("<" + entry.getKey() + ">");
			buffer.append(entry.getValue());
			buffer.append("</" + entry.getKey() + ">");
		}
		buffer.append("</xml>");

		return buffer.toString();
	}


	@SuppressWarnings("unchecked")
	public static Map<String, String> doXMLParse(String strXml) {
		Map<String, String> map = new HashMap<String, String>();
		Document doc = null;
		try {
			doc = DocumentHelper.parseText(strXml); // 将字符串转为XML
			Element root = doc.getRootElement(); // 获取根节点
			List<Element> list = root.elements();// 获取根节点下所有节点
			for (Element element : list) { // 遍历节点
				map.put(element.getName(), element.getText()); // 节点的name为map的key，text为map的value
			}
		} catch (DocumentException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return map;
	}


	/**
	 * 返回app前段调用数据
	 */
	public static String appInvokerData(String prepay_id, PayConfigParams configParams, String trade_type) {
		long second =  System.currentTimeMillis() / 1000L; //（转换成秒）
		SortedMap<String, String> signParam = new TreeMap<String, String>();

        if ("JSAPI".equalsIgnoreCase(trade_type)){
            signParam.put("appId", configParams.getAppid());//微信商户账号
            signParam.put("nonceStr", makeUUID()); // 预付订单id
            signParam.put("package", "prepay_id="+prepay_id); // 默认sign=WXPay
            signParam.put("signType", "MD5"); // 自定义不重复的长度不长于32位
            signParam.put("timeStamp", second + ""); // 北京时间时间戳
        }else {
            signParam.put("appid", configParams.getAppid());//app_id
            signParam.put("partnerid", configParams.getMch_id());//微信商户账号
            signParam.put("prepayid", prepay_id); // 预付订单id
            signParam.put("package", "Sign=WXPay"); // 默认sign=WXPay
            signParam.put("noncestr", makeUUID()); // 自定义不重复的长度不长于32位
            signParam.put("timestamp", String.valueOf(second).substring(0, 10)); // 北京时间时间戳
        }
		sign(signParam, configParams.getSign_key());
		return JSON.toJSONString(signParam);
	}

	
	/**
	 * 退款创建map
	 */
	public static SortedMap<String, String> createRequestRefundParams(PayRefundParams params, PayConfigParams configParams) {
		SortedMap<String, String> maps = new TreeMap<>();
		maps.put("out_refund_no", params.getOut_refund_no());
		maps.put("out_trade_no", params.getOut_trade_no());
		maps.put("refund_fee", String.valueOf(params.getRefund_fee()));
		maps.put("total_fee", String.valueOf(params.getTotal_fee()));
		maps.put("appid", configParams.getAppid());
		maps.put("mch_id", configParams.getMch_id());
		maps.put("nonce_str", makeUUID());
		
		return maps;
	}
	
	
	/**
	 * 回调返回xml数据
	 * @param result SUCCESS/FAIL
	 * @param msg   OK 返回信息，如非空，为错误原因：签名失败
	 * @return
	 */
	public static String callBackReturn(String result, String msg) {
		StringBuffer buffer = new StringBuffer();
		buffer.append("<xml><return_code><![CDATA[");
		buffer.append(result);
		buffer.append("]]></return_code><return_msg><![CDATA[");
		buffer.append(msg);
		buffer.append("]]></return_msg></xml>");
		return buffer.toString();
	}

	public static SortedMap<String, String> createRequestSendRedPack(SendRedPackParams params, PayConfigParams configParams){
        SortedMap<String, String> maps = new TreeMap<>();
        maps.put("mch_billno", params.getMch_billno() );
        maps.put("send_name", params.getSend_name());
        maps.put("re_openid", params.getRe_openid());
        maps.put("total_amount", params.getTotal_amount() + "");
        maps.put("total_num", params.getTotal_num() + "");
        maps.put("wishing", params.getWishing());
        maps.put("client_ip", params.getClient_ip());
        maps.put("act_name", params.getAct_name());
        maps.put("remark", params.getRemark());
        maps.put("wxappid", configParams.getAppid());
        maps.put("mch_id", configParams.getMch_id());
        maps.put("nonce_str", makeUUID());
        return maps;
    }
}
